package com.campuscrowdsourcing.server.controller;


import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.campuscrowdsourcing.server.annotation.Log;
import com.campuscrowdsourcing.server.annotation.LoginCheck;
import com.campuscrowdsourcing.server.common.enums.Action;
import com.campuscrowdsourcing.server.domain.dto.user.TaskDTO;
import com.campuscrowdsourcing.server.domain.entity.Task;
import com.campuscrowdsourcing.server.domain.entity.TaskCheck;
import com.campuscrowdsourcing.server.domain.entity.TaskType;
import com.campuscrowdsourcing.server.domain.entity.User;
import com.campuscrowdsourcing.server.domain.model.AjaxResult;
import com.campuscrowdsourcing.server.domain.vo.TaskVO;
import com.campuscrowdsourcing.server.service.TaskCheckService;
import com.campuscrowdsourcing.server.service.TaskService;
import com.campuscrowdsourcing.server.service.TaskTypeService;
import com.campuscrowdsourcing.server.service.UserService;
import com.campuscrowdsourcing.server.utils.RequestUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 任务信息		salary、score自动填充0		若发起者、父级任务被删除，该信息直接删除	若接受者、任务查看权限被删除，接受者、任务查看权限一栏设置为空	若任务类型被删除，由于存在该类型的任务，故该类型不允许被删除	任何外键信息更新时，该信息随之更新		任务接受者仅有一次修改任务查看权限的机会（生成信息时）	若任务查看权限不为空接受者必须为对应团队的管理员	若任务查看权限不为空则报酬与对应的团队对接，接受任务的管理员	若任务查看权限不为空且该团队不存在则不允许提交完成任务		接受者接受任务的团队内的管理员及以上权限者可以创建该任务的子任务	子任务的奖励以积分的形式表现	积分当且仅当为子任务时可填写	查看权限(为空时所有用户可见,否则为团队id)		任务的创建时间和更新时间不需要手动修改,信息建立时更新创建时间,修改时更新 更新时间	 前端控制器
 * </p>
 *
 * @author Xinyuan Zhao
 * @since 2023-03-14
 */
@RestController
@RequestMapping("/api/task")
public class TaskController {
    @Resource
    private TaskService taskService;
    @Resource
    private UserService userService;
    @Resource
    private TaskCheckService taskCheckService;
    @Resource
    private TaskTypeService taskTypeService;

    @PostMapping
    @Log(title = "新增任务", action = Action.INSERT)
    public AjaxResult saveTask(@RequestBody @Validated Task task) {
        taskService.save(task);
        return AjaxResult.success();
    }


    @Log(title = "修改任务", action = Action.UPDATE)
    @PutMapping
    public AjaxResult update(@RequestBody @Validated Task task) {
        taskService.updateById(task);
        return AjaxResult.success();
    }

    @DeleteMapping("/{id}")
    @Log(title = "删除任务", action = Action.DELETE)
    public AjaxResult delete(@PathVariable Integer id) {
        taskService.removeById(id);
        return AjaxResult.success();
    }


    @GetMapping
    @Log(title = "查看全部", action = Action.SELECT)
    public AjaxResult listTask() {
        return AjaxResult.success(taskService.list());
    }

    @GetMapping("/{id}")
    @Log(title = "id查询任务", action = Action.SELECT)
    public AjaxResult getTaskById(@PathVariable Integer id) {
        Task task = taskService.getById(id);
        if(task == null)
        {
            return AjaxResult.fail("该任务已删除或不存在");
        }
        return AjaxResult.success(task);
    }

    @GetMapping("/taskUser/{id}")
    @Log(title = "id查询任务(含发布者)", action = Action.SELECT)
    public AjaxResult getTaskUserById(@PathVariable Integer id) {
        Task task = taskService.getById(id);
        if(task == null)
        {
            return AjaxResult.fail("该任务已删除或不存在");
        }
        Map<String,Object> map = new HashMap<>();
        TaskVO taskVO = new TaskVO();
        BeanUtils.copyProperties(task,taskVO);
        taskVO.setTypeName(taskTypeService.getById(task.getType()).getTypeName());
        map.put("task",taskVO);
        User user = userService.getById(task.getAuthor());
        map.put("author",user);
        List<TaskCheck>taskChecks = taskCheckService.list();
        List<User> users = new ArrayList<>();
        for (TaskCheck taskCheck : taskChecks) {
            if(taskCheck.getTaskId().equals(id))
            {
                users.add(userService.getById(taskCheck.getUserId()));
            }
        }
        map.put("users",users);
        List<Task> tasks = taskService.list();
        Integer taskNum = 0;
        for (Task task1 : tasks) {
            if(task1.getAudit().equals(task.getAudit()))
            {
                taskNum ++;
            }
        }
        map.put("taskNum",taskNum);
        return AjaxResult.success(map);
    }

    @GetMapping("/teamCount/{id}")
    @Log(title = "查询指定团队任务数量", action = Action.SELECT)
    public AjaxResult getTeamCount(@PathVariable Integer id) {
        return AjaxResult.success(taskService.findTeamCount(id));
    }

    @GetMapping("/page")
    @Log(title = "分页查询", action = Action.SELECT)
    public AjaxResult listTaskPage(@RequestParam(defaultValue = "") String name,
                               @RequestParam Integer pageNum,
                               @RequestParam Integer pageSize) {
        QueryWrapper<Task> queryWrapper = new QueryWrapper<Task>().orderByDesc("id");
        queryWrapper.like(!"".equals(name), "name", name);
        return AjaxResult.success(taskService.page(new Page<>(pageNum, pageSize), queryWrapper));
    }

    @PutMapping("/accept")
    @Log(title = "任务审核", action = Action.SELECT)
    @LoginCheck
    public AjaxResult taskAccept(@RequestParam Integer taskId,
                             @RequestParam(required = false) Integer teamId) {
        Integer userId = RequestUtil.getCurrentUserId();
        taskService.Accept(userId,taskId,teamId);
        return AjaxResult.success();
    }

    @PostMapping("/showAcceptablePage")
    @Log(title = "任务大厅分页查询", action = Action.SELECT)
    //审核通过 未被接受  非子任务
    public AjaxResult getTaskAcceptablePage(@RequestBody @Validated TaskDTO taskDTO) {
        QueryWrapper<Task> queryWrapper = new QueryWrapper<Task>().orderByDesc("id");
        queryWrapper.like(!"".equals(taskDTO.getName()), "name", taskDTO.getName());
        queryWrapper.eq("audit",true);
        if(!taskDTO.getType().equals("0"))
        {
            queryWrapper.eq("type",taskDTO.getType());
        }
        if(taskDTO.getMinPlanB() != 0)
        {
            queryWrapper.ge("salary",taskDTO.getMinPlanB());
        }
        if(taskDTO.getMaxPlanB() != 0)
        {
            queryWrapper.le("salary",taskDTO.getMaxPlanB());
        }
        queryWrapper.isNull("pid");
        queryWrapper.isNull("worker");
        return AjaxResult.success(taskService.page(new Page<>(taskDTO.getPageNum(), taskDTO.getPageSize()), queryWrapper));
    }
    @GetMapping("/showAcceptPage")
    @Log(title = "我的接受分页查询", action = Action.SELECT)
    @LoginCheck
    //审核通过 我的接受  非子任务
    public AjaxResult getTaskAcceptPage(@RequestParam(defaultValue = "") String name,
                                         @RequestParam Integer pageNum,
                                         @RequestParam Integer pageSize) {
        Integer id = RequestUtil.getCurrentUserId();
        QueryWrapper<Task> queryWrapper = new QueryWrapper<Task>().orderByDesc("id");
        queryWrapper.like(!"".equals(name), "name", name);
        queryWrapper.eq("audit",true);
        queryWrapper.isNull("pid");
        queryWrapper.eq("worker",id);
        return AjaxResult.success(taskService.page(new Page<>(pageNum, pageSize), queryWrapper));
    }
    @GetMapping("/showMyPage")
    @Log(title = "我的接受分页查询", action = Action.SELECT)
    @LoginCheck
    //审核通过 我的发布  非子任务
    public AjaxResult getMyTaskPage(@RequestParam(defaultValue = "") String name,
                                     @RequestParam Integer pageNum,
                                     @RequestParam Integer pageSize) {
        Integer id = RequestUtil.getCurrentUserId();
        QueryWrapper<Task> queryWrapper = new QueryWrapper<Task>().orderByDesc("id");
        queryWrapper.like(!"".equals(name), "name", name);
        queryWrapper.eq("audit",true);
        queryWrapper.isNull("pid");
        queryWrapper.eq("author",id);
        return AjaxResult.success(taskService.page(new Page<>(pageNum, pageSize), queryWrapper));
    }

    @GetMapping("/teamPage")
    @Log(title = "分页团队任务", action = Action.SELECT)
    public AjaxResult listTeamPage(@RequestParam(defaultValue = "") String name,
                               @RequestParam Integer pageNum,
                               @RequestParam Integer pageSize,
                               @RequestParam Integer id) {
        QueryWrapper<Task> queryWrapper = new QueryWrapper<Task>().orderByDesc("id");
        queryWrapper.like(!"".equals(name), "name", name);
        queryWrapper.eq("role",id);
        Page<Task> page = taskService.page(new Page<>(pageNum, pageSize), queryWrapper);
        Map<String,Object> map;
        map = taskService.teamPage(page);
        return AjaxResult.success(map);
    }

    @GetMapping("/teamPageing")
    @Log(title = "分页团队进行中任务", action = Action.SELECT)
    public AjaxResult findTeamPageing(@RequestParam(defaultValue = "") String name,
                                  @RequestParam Integer pageNum,
                                  @RequestParam Integer pageSize,
                                  @RequestParam Integer id) {
        QueryWrapper<Task> queryWrapper = new QueryWrapper<Task>().orderByDesc("id");
        queryWrapper.like(!"".equals(name), "name", name);
        queryWrapper.eq("role",id);
        queryWrapper.eq("finish",0);
        Page<Task> page = taskService.page(new Page<>(pageNum, pageSize), queryWrapper);
        Map<String,Object> map;
        map = taskService.teamPage(page);
        return AjaxResult.success(map);
    }

    @GetMapping("/teamPageFinish")
    @Log(title = "分页团队已完成任务", action = Action.SELECT)
    public AjaxResult findTeamPageFinish(@RequestParam(defaultValue = "") String name,
                                     @RequestParam Integer pageNum,
                                     @RequestParam Integer pageSize,
                                     @RequestParam Integer id) {
        QueryWrapper<Task> queryWrapper = new QueryWrapper<Task>().orderByDesc("id");
        queryWrapper.like(!"".equals(name), "name", name);
        queryWrapper.eq("role",id);
        queryWrapper.eq("finish",1);
        Page<Task> page = taskService.page(new Page<>(pageNum, pageSize), queryWrapper);
        Map<String,Object> map;
        map = taskService.teamPage(page);
        return AjaxResult.success(map);
    }

    /**
     * 导出接口
     */
    @GetMapping("/export")
    public void export(HttpServletResponse response) throws Exception {
        // 从数据库查询出所有的数据
        List<Task> list = taskService.list();
        // 在内存操作，写出到浏览器
        ExcelWriter writer = ExcelUtil.getWriter(true);

        // 一次性写出list内的对象到excel，使用默认样式，强制输出标题
        writer.write(list, true);

        // 设置浏览器响应的格式
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        String fileName = URLEncoder.encode("Task信息表", "UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");

        ServletOutputStream out = response.getOutputStream();
        writer.flush(out, true);
        out.close();
        writer.close();
    }

    /**
     * excel 导入
     * @param file
     * @throws Exception
     */
    @PostMapping("/import")
    public AjaxResult imp(MultipartFile file) throws Exception {
        InputStream inputStream = file.getInputStream();
        ExcelReader reader = ExcelUtil.getReader(inputStream);
        // 通过 javabean的方式读取Excel内的对象，但是要求表头必须是英文，跟javabean的属性要对应起来
        List<Task> list = reader.readAll(Task.class);

        taskService.saveBatch(list);
        return AjaxResult.success();
    }
}

